<template>
  <div class="app-container home"
       ref="home"
       :class="[device === 'mobile' ? 'mobile-device' : '']">
    <!-- <MarkmapRender :content="markmapContent"></MarkmapRender> -->
    <!-- <MarkmapRender :content="markmapContent"></MarkmapRender> -->
    <!-- <markdown-it-vue class="md-body"
                     :content="markdownContent"
                     :options="options"
                     @render-complete="hdlCmplete" /> -->
    <!-- <Markdown :content="htmlinner" /> -->
    <!-- <v-md-preview
                          :text="Markdowncontent"
                         
                        /> -->
    <!-- <span>{{ katexRender }}</span> -->
    <div class="main px-xl-5 px-lg-4 px-3">
      <div class="chat-body">
        <!-- Chat Box Header -->
        <!-- end Chat Box Header -->

        <div class="chat-content"
             id="scrollRef"
             ref="scrollRef">
          <!-- <v-md-preview :text="receive"
                        ref="receive" /> -->
          <div :class="containerTotal()">
            <ul class="list-unstyled py-4"
                v-for="(item, index) in messageList"
                :key="index">
              <li class="d-flex message right message-send-li">
                <div class="message-body">
                  <span class="date-time text-muted"></span>
                  <div class="message-row align-items-center justify-content-end">
                    <div class="message-send-title message-content">
                      <div class="message-user-icon">
                        <img :src="avatar"
                             class="userprofile" />
                      </div>
                      <div>
                        <div class="message-user-ques">{{ item.send }}</div>
                        <ul class="attachment-file"
                            v-if="item.attachmentFile.length">
                          <li v-for="(iitem, key) in item.attachmentFile"
                              :key="key"
                              :class="['attachment-file-item','attachment-file-item-'+iitem.extension]">
                            <div class="attachment-name">
                              <svg-icon :icon-class="iitem.extension" />{{ iitem.name }}
                            </div>
                          </li>
                        </ul>
                      </div>
                    </div>
                  </div>
                </div>
              </li>
              <li class="message-answer-total">
                <div class="message-body d-flex message"
                     v-if="item.loading">
                  <div class="message-row d-flex">
                    <div class="message-content">
                      <div class="wave">
                        <span class="dot"></span>
                        <span class="dot"></span>
                        <span class="dot"></span>
                      </div>
                    </div>
                  </div>
                </div>

                <ul class="message-answer"
                    v-else>
                  <li class="d-flex message"
                      v-if="item.receive">
                    <div class="message-body">
                      <div class="message-row d-flex align-items-center">
                        <div class="message-reply message-content">
                          <div class="message-user-icon">
                            <div class="message-reply-icon">
                              <img :src="headImg"
                                   class="reply-icon" />
                            </div>
                          </div>

                          <div class="message-answer-all">
                            <div class="message-reply-cont"
                                 :id="'message-reply-cont' + index">
                              <div class=""
                                   v-html="item.resource"
                                   @click.stop="relationQuestionClick($event)"></div>
                              <markdown-it-vue :content="item.receive"
                                               :options="options"
                                               @markdowndataprocess="totalResultAnswerProcess"
                                               @render-complete="hdlCmplete"
                                               @click.native.stop="
                                  relationQuestionClick($event)
                                " />
                              <div class="voice-copy"
                                   :id="'voice-copy' + index">
                                <div @click="speakText(index)"
                                     class="voice-icon">
                                  <svg-icon icon-class="voice" />
                                </div>
                                <div @click="copyText(index)"
                                     class="copy-icon">
                                  <svg-icon icon-class="copy" />
                                </div>

                                <div @click="shareDialog()"
                                     class="share-icon">
                                  <svg-icon icon-class="share" />
                                </div>
                              </div>
                            </div>
                            <div class="swiper-cont"
                                 :style="{
                                width:
                                  device === 'mobile' ? swiperWidth : '300px',
                              }">
                              <swiper :send="item.send"
                                      :imageList="item.imageList"
                                      :isMarkmapContentDone="
                                  item.isMarkmapContentDone
                                "
                                      :markmapContent="item.markmapContent"
                                      :markmapid="index"
                                      @imagepop="imagepop"
                                      @markmappop="markmappop" />
                            </div>
                          </div>
                        </div>
                      </div>
                    </div>
                  </li>
                </ul>
              </li>
            </ul>
          </div>
        </div>
      </div>
    </div>
    <div class="chat-footer border-top py-xl-4 py-lg-2 py-2"
         :style="{ width: computedWidth + 'px' }">
      <div class="chat-footer-in"
           @dragover.stop.prevent="handleDragOver"
           @drop.stop.prevent="handleFileDrop">
        <div class="row">
          <div class="row-fill-form">
            <ul class="attachment-file"
                v-if="attachmentFile.length">
              <li v-for="(item, key) in attachmentFile"
                  :key="key"
                  :class="['attachment-file-item','attachment-file-item-'+item.extension]">
                <div class="btn-close-svg"
                     @click="deleteAttachmentFile(key)">
                  <svg viewBox="0 0 24 24"
                       xmlns="http://www.w3.org/2000/svg"
                       width="24"
                       height="24"
                       fill="currentColor">
                    <path d="M11.9997 10.5865L16.9495 5.63672L18.3637 7.05093L13.4139 12.0007L18.3637 16.9504L16.9495 18.3646L11.9997 13.4149L7.04996 18.3646L5.63574 16.9504L10.5855 12.0007L5.63574 7.05093L7.04996 5.63672L11.9997 10.5865Z"></path>
                  </svg>
                </div>
                <div class="attachment-name">
                  <svg-icon :icon-class="item.extension" />{{ item.name }}
                </div>
                <div class="attachment-detail">
                  <div>{{ item.size }}</div>
                </div>
              </li>
            </ul>
            <div class="input-group align-items-center">
              <input type="text"
                     @keyup.enter="keyDown"
                     v-model="prompt"
                     class="input-form-control"
                     placeholder="Type your message..." />
            </div>

            <div class="chat-focus-list">
              <div class="chat-focus"
                   @click="showpop('focus')">
                <span class="el-icon-setting"></span>{{ languagetypeCn[languagetype] }}
              </div>
              <div class="chat-focus"
                   @click="showpop('attachment')">
                <span class="el-icon-circle-plus-outline"></span>附加
              </div>

              <!-- <div
                :class="{ 'chat-focus': true, 'chat-focus-disable': !taskId }"
                @click.stop="messages_stop"
              >
                <span class="el-icon-circle-plus-outline"></span>停止对话
              </div> -->
            </div>
          </div>

          <div class="input-group-append">
            <span class="input-group-text border-0 pr-0">
              <button type="submit"
                      :class="[
                  'btn',
                  duringTask ? 'btn-submit-disable' : 'btn-submit-active',
                ]"
                      @click.stop="handleSubmit">
                <svg-icon :icon-class="[buttonDisabled ? 'stop' : 'guide']"
                          class="guide-icon" />
              </button>
            </span>
          </div>
        </div>

        <ul class="attachmentlist"
            v-if="isfocus">
          <!-- <div class="btn-close-svg" @click="closepop('focus')">
            <svg
              viewBox="0 0 24 24"
              xmlns="http://www.w3.org/2000/svg"
              width="24"
              height="24"
              fill="currentColor"
            >
              <path
                d="M11.9997 10.5865L16.9495 5.63672L18.3637 7.05093L13.4139 12.0007L18.3637 16.9504L16.9495 18.3646L11.9997 13.4149L7.04996 18.3646L5.63574 16.9504L10.5855 12.0007L5.63574 7.05093L7.04996 5.63672L11.9997 10.5865Z"
              ></path>
            </svg>
          </div> -->
          <li class="el-icon-box type-icon"
              :class="{ 'type-icon-active': languagetype === 'general' }"
              @click="getchange('general')">
            <div class="txt">通用</div>
          </li>
          <li class="el-icon-star-off type-icon"
              :class="{ 'type-icon-active': languagetype === 'science' }"
              @click="getchange('science')">
            <div class="txt">学术</div>
          </li>
        </ul>
        <ul class="attachmentlist"
            v-if="isAttachment">
          <div class="btn-close-svg"
               @click="closepop('attachment')">
            <svg viewBox="0 0 24 24"
                 xmlns="http://www.w3.org/2000/svg"
                 width="24"
                 height="24"
                 fill="currentColor">
              <path d="M11.9997 10.5865L16.9495 5.63672L18.3637 7.05093L13.4139 12.0007L18.3637 16.9504L16.9495 18.3646L11.9997 13.4149L7.04996 18.3646L5.63574 16.9504L10.5855 12.0007L5.63574 7.05093L7.04996 5.63672L11.9997 10.5865Z"></path>
            </svg>
          </div>
          <li>
            <el-upload class="upload-demo"
                       action="#"
                       ref="upload"
                       :show-file-list="false"
                       :file-list="fileList"
                       :http-request="handleFileUpload">
              <div class="upload-icon-txt">
                <i class="el-icon-upload"></i>
                <div class="el-upload__text">附加</div>
              </div>
            </el-upload>
          </li>
        </ul>
      </div>
    </div>
    <el-dialog class="imagepop-dialog"
               :visible.sync="imagePopVisible"
               @close="handleClose">
      <searchImagePage :message="message" />
    </el-dialog>

    <el-dialog class="imagepop-dialog"
               :visible.sync="markmapPopVisible"
               @close="markmaphandleClose">
      <MarkmapRender :content="markmapContent"
                     :contentwidth="full"
                     :markmapid="markmapid" />
    </el-dialog>

    <el-dialog class="selectimage-dialog"
               :visible.sync="imageSelectPopVisible"
               @close="handleClose">
      <div class="">
        <div class="chat-content selectimagechatContent"
             :style="{ height: imageSelectsharepopheight + 'px' }">
          <div id="selectimagechatContent">
            <ul class="list-unstyled py-4"
                v-for="(item, index) in selectMessageList"
                :key="index">
              <li class="d-flex message right message-send-li"
                  v-if="item.send">
                <div class="message-body">
                  <span class="date-time text-muted"></span>
                  <div class="message-row align-items-center justify-content-end">
                    <div class="message-send-title message-content">
                      <div class="message-user-icon">
                        <img :src="avatar"
                             class="userprofile" />
                      </div>
                      <div class="message-user-ques">{{ item.send }}</div>
                    </div>
                  </div>
                </div>
              </li>
              <li class="message-answer-total"
                  v-if="item.receive">
                <ul class="message-answer">
                  <li class="d-flex message">
                    <div class="message-body">
                      <div class="message-row d-flex align-items-center">
                        <div class="message-reply message-content">
                          <div class="message-user-icon">
                            <div class="message-reply-icon">
                              <img :src="headImg"
                                   class="reply-icon" />
                            </div>
                          </div>

                          <div class="message-answer-all">
                            <div class="message-reply-cont"
                                 :id="'message-reply-cont' + index">
                              <div class=""
                                   v-html="item.resource"
                                   @click.stop="relationQuestionClick($event)"></div>
                              <markdown-it-vue :content="item.receive"
                                               :options="options"
                                               @markdowndataprocess="totalResultAnswerProcess"
                                               @render-complete="hdlCmplete"
                                               @click.native.stop="
                                  relationQuestionClick($event)
                                " />
                            </div>

                            <div class="swiper-cont"
                                 :style="{width: device === 'mobile' ? swiperWidth : '300px'}">
                              <swiper :send="item.send"
                                      :imageList="item.imageList"
                                      :isMarkmapContentDone="item.isMarkmapContentDone"
                                      :markmapContent="item.markmapContent"
                                      :markmapid="index"
                                      @imagepop="imagepop"
                                      @markmappop="markmappop" />
                            </div>
                          </div>
                        </div>
                      </div>
                    </div>
                  </li>
                </ul>
              </li>
            </ul>
          </div>
        </div>
        <ul class="save-images-btns">
          <li @click="copyImage"
              class="copy-btn">
            <svg-icon icon-class="copy" />复制图片
          </li>
          <li @click="saveImage"
              class="downloadfile-btn">
            <svg-icon icon-class="downloadfile" />保存图片
          </li>
        </ul>
      </div>
    </el-dialog>

    <el-dialog class="sharepop-dialog"
               :visible.sync="sharePopVisible"
               @close="handleClose">
      <div class="chat-content-all">
        <div class="chat-content"
             id="chatContent"
             :style="{ height: sharepopheight + 'px' }">
          <el-checkbox-group v-model="checkboxlist"
                             @change="shareCheckboxChange">
            <ul class="list-unstyled py-4"
                v-for="(item, index) in messageList"
                :key="index">
              <!-- Right Message -->
              <li class="d-flex message right message-send-li">
                <div class="checkbox-select">
                  <el-checkbox :key="'send-' + index"
                               :label="'send-' + index"><br /></el-checkbox>
                </div>
                <div class="message-body">
                  <span class="date-time text-muted"></span>
                  <div class="message-row align-items-center justify-content-end">
                    <div class="message-send-title message-content">
                      <div class="message-user-icon">
                        <img :src="avatar"
                             class="userprofile" />
                      </div>
                      <div class="message-user-ques">{{ item.send }}</div>
                    </div>
                  </div>
                </div>
              </li>
              <li class="message-answer-total">
                <div class="checkbox-select">
                  <el-checkbox :key="'receive-' + index"
                               :label="'receive-' + index"><br /></el-checkbox>
                </div>

                <ul class="message-answer">
                  <li class="d-flex message"
                      v-if="item.receive">
                    <div class="message-body">
                      <div class="message-row d-flex align-items-center">
                        <div class="message-reply message-content">
                          <div class="message-user-icon">
                            <div class="message-reply-icon">
                              <img :src="headImg"
                                   class="reply-icon" />
                            </div>
                          </div>

                          <div class="message-answer-all">
                            <div
                              class="message-reply-cont"
                              :id="'message-reply-cont' + index"
                            >
                              <div
                                class=""
                                v-html="item.resource"
                                @click.stop="relationQuestionClick($event)"
                              ></div>
                              <markdown-it-vue
                                :content="item.receive"
                                :options="options"
                                @markdowndataprocess="totalResultAnswerProcess"
                                @render-complete="hdlCmplete"
                                @click.native.stop="
                                  relationQuestionClick($event)
                                "
                              />
                            </div>
                            <div class="swiper-cont"
                                 :style="{
                                width:
                                  device === 'mobile'
                                    ? selectSwiperWidth
                                    : '300px',
                              }">
                              <swiper :send="item.send"
                                      :imageList="item.imageList"
                                      :isMarkmapContentDone="
                                  item.isMarkmapContentDone
                                "
                                      :markmapContent="item.markmapContent"
                                      :markmapid="index"
                                      @imagepop="imagepop"
                                      @markmappop="markmappop" />
                            </div>
                          </div>
                        </div>
                      </div>
                    </div>
                  </li>
                </ul>
              </li>
            </ul>
          </el-checkbox-group>
        </div>
        <ul class="share-btn-all">
          <li @click="copylink"
              :class="[
              'copylink-btn',
              createimageDisable ? 'create-image-disable-btn' : '',
            ]">
            <svg-icon icon-class="links" />复制链接
          </li>

          <li @click="createImage"
              :class="[
              'create-image-btn',
              createimageDisable ? 'create-image-disable-btn' : '',
            ]">
            <svg-icon icon-class="picture" />生成图片
          </li>
        </ul>
      </div>
    </el-dialog>

    <a id="downimg"
       href=""
       style="display: none"></a>
  </div>
</template>

<script>
import { fetchEventSource } from "@microsoft/fetch-event-source";
import {
  conversations,
  messages,
  upload,
  messagesStop,
  search_image,
  markmapreq,
} from "@/api/ai";
import { addchattopic, addchatdetail } from "@/api/chat";
import { v4 } from "uuid";
import qs from "qs";
import { mapGetters, mapActions } from "vuex";
import { scrollTo } from "@/utils/scroll-to";
import { formatBytes, deepClone } from "@/utils";
import MarkdownItVue from "@/components/markdown";
import MarkmapRender from "@/components/markmap/allindex";
// import Markdownnew from "@/components/Markdownnew.vue";
// import katex from "katex";
// import "katex/dist/katex.css";
// import markmap from "@/components/markmap";
import swiper from "@/components/swiper";
import searchImagePage from "@/views/searchImagePage";
import axios from "axios";
import html2canvas from "html2canvas";
export default {
  name: "Index",
  components: {
    swiper,
    MarkmapRender,
    MarkdownItVue,
    searchImagePage,
  },
  data () {
    return {
      createimageDisable: true,
      selectMessageList: [],
      checkboxlist: [],
      imageSelectHtml: "",
      sharePopVisible: false,
      imageSelectPopVisible: false,
      markmapid: "",
      full: "full",
      message: "",
      markmapContent: "",
      imagePopVisible: false,
      markmapPopVisible: false,
      imageList: [],
      swiperOption: {
        autoplay: false,
        loop: false,
        spaceBetween: 10,
        observer: true,
        observeParents: true,
        on: {
          slideChangeTransitionEnd: function () {
            _this.isActiveIndex = this.realIndex; //切换结束时，告诉我现在是第几个slide
            _this.type = _this.cardList[_this.isActiveIndex].cardType;
            _this.cardInfoList = [];
            _this.pageNo = 1;
            _this.isScroll = true;
            _this.loading = true;
            _this.getListData();
          },
        },
      },
      tabName: "name1",
      labelRender (h) {
        return h("div", "购物车");
      },

      markdownContent:
        "\\[ b_n = \\frac{2}{T} \\int_{-\\frac{T}{2}}^{\\frac{T}{2}} f(t) \\sin\\left(\\frac{2\\pi n t}{T}\\right) dt \\] [2]\n\n###",
      // "1. **傅里叶变换**：傅里叶变换将一个时域信号转换为频域信号，其公式为：其公式为：\n   \\[\n   F(\\omega) = \\int_{-\\infty}^{+\\infty} f(t) e^{-i\\omega t} \\, dt \n [6]  \\] 文字 \n \n\\[ f(t) = \\frac{a_0}{2} + \\sum_{n=1}^{\\infty} \\left[ a_n \\cos\\left(\\frac{2\\pi n t}{T}\\right) + b_n \\sin\\left(\\frac{2\\pi n t}{T}\\right) \\right] \\]",
      // // "1. 傅里叶变换：傅里叶变换将一个时域信号转换为频域信号，其公式为：\n   \\[\n   F(\\omega) = \\int_{-\\infty}^{+\\infty} f(t) e^{-i\\omega t} \\, dt  [6] \n   \\]\n ",
      // content: "#*urls:[1]: https://www.cnblogs.com/jsfantasy/p/12177275.html\n[2]: https://www.cnblogs.com/wlzy/p/7751297.html\n[3]: https://www.cnblogs.com/zhoushusheng/p/18563781\n[4]: https://segmentfault.com/a/1190000021529971\n[5]: https://zhuanlan.zhihu.com/p/37916911\n[6]: https://blog.csdn.net/zhaohongfei_358/article/details/120987506\n[7]: https://cloud.tencent.com/developer/article/1909271\n[8]: https://www.cnblogs.com/jins-note/p/12556270.html\n[9]: https://blog.csdn.net/dare_kz/article/details/77603522\n[10]: https://blog.csdn.net/qiantianye/article/details/144536148\n[11]: https://blog.csdn.net/qq_42410605/article/details/142515911\n[12]: https://blog.csdn.net/weixin_44204324/article/details/107561007\n[13]: https://www.cnblogs.com/BlairGrowing/p/14982115.html\n[14]: https://blog.csdn.net/weixin_51385258/article/details/143984008\n[15]: https://www.imooc.com/article/269657\n[16]: https://blog.csdn.net/2301_77509762/article/details/144003101\n[17]: https://blog.csdn.net/qq_45912037/article/details/128073903\n[18]: https://blog.csdn.net/deephub/article/details/121649161\n[19]: https://blog.csdn.net/qq_29407397/article/details/90599460\n[20]: https://blog.csdn.net/november_chopin/article/details/103900937\n[21]: https://blog.csdn.net/m0_64227668/article/details/133547025\n[22]: https://zhuanlan.zhihu.com/p/80376257\n[23]: https://blog.csdn.net/qq_67654130/article/details/143788125\n[24]: https://www.cnblogs.com/lzhu/p/10339392.html\n[25]: https://zhuanlan.zhihu.com/p/61898234\n[26]: https://martinlwx.github.io/zh-cn/backpropagation-tutorial/\n[27]: https://blog.csdn.net/qq_53324833/article/details/143251909\n[28]: https://blog.csdn.net/xuan_liu123/article/details/83660316\n[29]: https://blog.csdn.net/zyqdragon/article/details/72804301\n[30]: https://blog.csdn.net/Serins/article/details/121508468\n[31]: https://blog.csdn.net/qq_35357274/article/details/108904265\n[32]: https://cloud.baidu.com/article/1959530\n[33]: https://zhuanlan.zhihu.com/p/682853418\n[34]: https://blog.csdn.net/EngineerofAI/article/details/125746470\n[35]: https://zhuanlan.zhihu.com/p/41392664\n[36]: https://blog.csdn.net/weixin_40673873/article/details/107398278\n[37]: https://zhuanlan.zhihu.com/p/40378224\n[38]: https://zhuanlan.zhihu.com/p/25496760\n[39]: https://blog.csdn.net/kkang_98/article/details/144645794\n[40]: https://blog.csdn.net/2401_85328934/article/details/141598050\n[41]: https://zhuanlan.zhihu.com/p/79657669\n[42]: https://blog.csdn.net/wyf2017/article/details/109359917\n[43]: https://zhuanlan.zhihu.com/p/662487898\n[44]: https://www.jianshu.com/p/3cebbeeaed71\n[45]: https://zhuanlan.zhihu.com/p/273595649\n[46]: https://blog.csdn.net/m0_53605808/article/details/144604887\n[47]: https://zhuanlan.zhihu.com/p/66534632\n[48]: https://blog.csdn.net/2301_77514963/article/details/144003291\n[49]: https://www.cnblogs.com/hello-ai/p/10885202.html\n[50]: https://blog.csdn.net/m0_46378271/article/details/124967496[SEP]神经网络之反向传播算法（BP）公式推导（超详细） - 博客园\n反向传播算法（过程及公式推导） - ZYVV - 博客园\n人工智能之深度学习基础——反向传播（Backpropagation）\n深度学习 - 神经网络之反向传播算法（BP）公式推导 (超详细 ...\n反向传播四：反向传播的4个公式 - 知乎\n详解+推导 神经网络中的前向传播和反向传播公式（神经 ...\n神经网络背后的数学原理：反向传播过程及公式推导 - 腾讯云\n神经网络前向传播和反向传播公式 详细推导 - Jerry_Jin - 博客园\nBP神经网络计算过程详解，用笔手算一遍弄懂反向传播 ...\nYOLO系列正传（三）神经网络的反向传播（back propagation ...\n深度学习——前向传播与反向传播、神经网络（前馈神经网络 ...\n由浅到深的神经网络正向传播与反向传播公式推导（吴恩达 ...\n深度学习——前向传播算法和反向传播算法（BP算法）及其 ...\n【神经网络基础-07】：反向传播算法 - CSDN博客\n【深度学习】反向传播算法——原理介绍与推导（最强版 ...\n神经网络的公式推导与代码实现_神经网络推导-CSDN博客\n【CNN基础知识】一文详解反向传播（Backpropagation ...\n神经网络背后的数学原理：反向传播过程及公式推导 - CSDN博客\n【机器学习】彻底理解神经网络中的反向传播算法（BP ...\n神经网络之反向传播算法（BP）公式推导 - CSDN博客\nCNN反向传播原理!(超级详细地推导)-CSDN博客\n【吴恩达深度学习】—深度神经网络的反向传播推导 - 知乎\n什么是反向传播算法_7、在神经网络的训练过程中,什么是反向 ...\n从梯度下降到反向传播(附计算例子) - 瘋子朱磊 - 博客园\n卷积神经网络(CNN)反向传播算法推导 - 知乎\n反向传播公式推导和理解 - MartinLwx's Blog\n一文彻底弄懂误差反向传播与梯度下降算法 - CSDN博客\n吴恩达机器学习视频--神经网络反向传播算法公式推导 ...\n神经网络中的反向传播法算法推导及matlab代码实现\n神经网络反向传播算法及代码实现_反向传播算法代码-CSDN博客\n神经网络学习笔记（3）——梯度下降公式讲解与反向传播算法 ...\n神经网络：公式推导与反向传播算法 - 百度智能云\n彻底弄懂，神经网络的误差反向传播算法 - 知乎\nBP神经网路详解 (误差反向传播-链式求导法则） - CSDN博客\n反向传播算法推导-卷积神经网络 - 知乎\n卷积神经网络 (CNN)反向传播算法&训练过程\nBack Propagation（梯度反向传播）实例讲解 - 知乎\n神经网络中利用矩阵进行反向传播运算的实质 - 知乎\nPSO-BP分类-粒子群优化算法（Particle Swarm Optimization ...\n神经网络算法 - 一文搞懂Back Propagation（反向传播）\n反向传播算法推导过程（非常详细） - 知乎专栏\n误差反向传播（手把手教你推导如何通过反向传播更新参数 ...\n反向传播最佳总结——一篇文章读懂神经网络反向传播 - 知乎\n全连接神经网络之反向传播算法原理推导 - 简书\n神经网络学习笔记-全连接神经网络的数学推导 - 知乎\n前馈神经网络的反向传播算法原理 - CSDN博客\n神经网络15分钟入门！——反向传播到底是怎么传播的？ - 知乎\n神经网络的公式推导与代码实现_神经网络权重更新公式 ...\n单层和双层神经网络反向传播公式推导(从矩阵求导的角度 ...\n[深度学习]激活函数(Sigmoid等)、前向传播、反向传播和梯度 ...\n\n反向传播算法（Backpropagation）在神经网络中用于计算损失函数对每个权重参数的梯度，其核心公式基于链式法则。以下是反向传播算法中的关键公式：\n\n1. **误差的反向传播**：对于输出层，误差信号定义为实际输出与期望输出之间的差异，即：\n   $$ \\delta^{(L)} = (a^{(L)} - y) \\cdot f'(z^{(L)}) $$\n   其中， $\\delta^{(L)}$  是输出层的误差，$a^{(L)}$ 是网络的预测输出，$y$ 是真实标签，$f'(z^{(L)})$ 是激活函数的导数。\n\n2. **隐藏层误差的计算**：对于第 $l$ 层（$l$ 不是输出层），误差信号定义为：\n   $$\\delta^{(l)} = (W^{(l+1)})^T \\cdot \\delta^{(l+1)} \\cdot f'(z^{(l)})$$\n   其中，$\\delta^{(l)}$ 是第 $l$ 层的误差，$W^{(l+1)}$ 是下一层（即第 $l+1$ 层）的权重矩阵，$f'(z^{(l)})$ 是第 $l$ 层激活函数的导数。\n\n3. **权重更新规则**：权重更新是通过梯度下降法实现的，公式为：\n   $$W^{(l)} = W^{(l)} - \\eta \\cdot \\frac{\\partial E}{\\partial W^{(l)}}$$\n   其中，$W^{(l)}$ 是第 $l$ 层的权重，$\\eta$ 是学习率，$\\frac{\\partial E}{\\partial W^{(l)}}$ 是损失函数 $E$ 对权重 $W^{(l)}$ 的偏导数。\n\n4. **偏置更新规则**：偏置更新也是通过梯度下降法实现的，公式为：\n   $$b^{(l)} = b^{(l)} - \\eta \\cdot \\frac{\\partial E}{\\partial b^{(l)}}$$\n   其中，$b^{(l)}$ 是第 $l$ 层的偏置，$\\eta$ 是学习率，$\\frac{\\partial E}{\\partial b^{(l)}}$ 是损失函数 $E$ 对偏置 $b^{(l)}$ 的偏导数。\n\n这些公式是反向传播算法中计算梯度和更新权重的核心，它们使得神经网络能够通过迭代学习来最小化损失函数[16], [48]。\n#*qsts:反向传播算法中链式法则是如何应用的？\n反向传播算法中权重更新的公式具体是怎么样的？\n在反向传播算法中，误差是如何反向传递的？\n反向传播算法中如何计算损失函数对权重参数的梯度？",
      activeTab: "t1",
      options: {
        markdownIt: {
          linkify: true,
        },
        linkAttributes: {
          attrs: {
            target: "_self",
            rel: "noopener",
          },
        },
      },
      isAttachment: false,
      attachmentFile: [],
      fileList: [],
      languagetype: "general",
      languagetypeCn: { general: "通用", science: "学术" },
      fileName: "",
      fileSize: 0,
      prompt: "",
      fileUploadCard: false,
      messageList: [],
      fileContent: "",
      formattedFileSize: "0B",
      conversationList: [],
      titlecontent: "",
      receive: "",
      abort: "",
      markmapabort: "",
      eventSource: null,
      object: {},
      windowsclientWidth: "",
      headImg: require("@/assets/logo.png"),
      isfocus: false,
      questionLineNum: 8,
      clearAutoScroll: false,
      timeclear: null,
      eventcount: 0,
      roundcount: 0,
      taskId: "",
      duringTask: false,
      buttonDisabled: false,
      katexRender: "",
      speechmsg: "",
    };
  },
  watch: {},
  computed: {
    ...mapGetters([
      "name",
      "sidebar",
      "device",
      "avatar",
      "chatList",
      "currentTopicId",
      "chatfromdify",
    ]),
    swiperWidth () {
      let width = document.documentElement.clientWidth - 90;
      return width + "px";
    },
    selectSwiperWidth () {
      let width = document.documentElement.clientWidth - 130;
      return width + "px";
    },
    computedWidth () {
      let _winwidth =
        this.windowsclientWidth -
        (this.device === "mobile" ? 0 : this.sidebar.opened ? 200 : 54) -
        40;
      return _winwidth;
    },
    sharepopheight () {
      const height = document.documentElement.clientHeight - 120;
      return height;
    },
    imageSelectsharepopheight () {
      let subtractheight = this.device === "mobile" ? 50 : 250;
      const height = document.documentElement.clientHeight - subtractheight;
      return height;
    },
    containerTotal () {
      return () => [
        this.attachmentFile.length ? "container-high" : "container-low",
      ];
    },
  },
  beforeMount () {
    // this.markdownContent = this.markdownContent.replace(/\s*\\\]/g, "$$$")
    //   .replace(/\\\[\s*/g, "$$$")
    //   .replace(/\\\(\s*/g, "$$")
    //   .replace(/\s*\\\)/g, "$$")

    // this.chattopic();
    window.addEventListener("resize", this._computedWidth);
  },
  beforeDestroy () {
    document.removeEventListener("click", this.handleClickOutside);
    window.removeEventListener("resize", this._computedWidth);
  },
  async mounted () {
    // let res = await search_image({ query: "老鹰" });
    // this.imageList = res;
    // console.log(res, "??????");

    // axios
    //   .get("static/markmapp.md")
    //   .then((response) => {
    //     this.markmapContent = response.data;
    //     console.log(response.data, "####");
    //   })

    //   .catch((error) => {});
    // this.markmap();
    // this.katexRender = katex.renderToString("c = \\pm\\sqrt{a^2 + b^2}");
    let _this = this;
    // document.onclick = function() {
    //     _this.clearAutoScroll = true
    // };
    document.addEventListener("click", this.handleClickOutside);
    this.questionLineNum = Math.floor(
      (this.$refs.home.offsetWidth - 130) / 160
    );
    this.initResize();
    window.addEventListener("resize", this.resizeFunction, false);

    this.$bus.$on("changeCurrentTopic", (topic_id) => {
      this.duringTask = false;
      this.attachmentFile = [];
      this.changeTocurrentTopic(topic_id, !this.chatfromdify);
    });
    let id = this.$route.query.id;
    if (id) {
      this.changeTocurrentTopic(id, !this.chatfromdify);
    }

    // this.conversations();
    this.windowsclientWidth = document.body.clientWidth;
  },
  beforeDestroy () {
    this.$bus.$off("changeCurrentTopic");
    this.removeResize();
  },
  methods: {
    ...mapActions("chat", ["getchattopic", "setCurrentTopicId"]),
    handleDragOver (e) {
      console.log(e)
    },
    handleFileDrop (e) {
      e.preventDefault();
      let files = e.dataTransfer.files;
      this.handleFileUpload({ file: files[0] })
      console.log(files, "????????????")
      // this.uploadFiles(files)
    },
    shareCheckboxChange () {
      let checkboxlist = this.checkboxlist;
      this.createimageDisable = checkboxlist.length ? false : true;
    },
    shareDialog () {
      this.sharePopVisible = true;
    },
    saveImage () {
      html2canvas(document.querySelector("#selectimagechatContent"), {
        useCORS: true,
      }).then((canvas) => {
        var url = canvas.toDataURL();
        document.querySelector("#downimg").href = url;
        document.querySelector("#downimg").download = "分享图片.png";
        document.querySelector("#downimg").click();
      });
    },
    copyImage () {
      html2canvas(document.querySelector("#selectimagechatContent"), {
        useCORS: true,
      }).then((canvas) => {
        var url = canvas.toDataURL();
        this.clipboardImg(url);
      });
    },
    async clipboardImg (url) {
      try {
        const data = await fetch(url);
        const blob = await data.blob();
        await navigator.clipboard.write([
          new window.ClipboardItem({
            [blob.type]: blob,
          }),
        ]);
        this.$message({
          type: "success",
          message: "复制成功",
        });
      } catch (err) {
        this.$message({
          type: "warning",
          message: "复制失败",
        });
      }
    },
    copylink () {
      let url = window.location.href;
      let domInput = document.createElement("input");
      domInput.value = url;
      document.body.appendChild(domInput);
      domInput.select();
      document.execCommand("Copy");

      this.$message({
        type: "success",
        message: "复制成功",
      });

      domInput.remove();
    },
    createImage () {
      // let node = this.$refs["receive-0"][0].cloneNode(true);
      let checkboxlist = this.checkboxlist;
      let list = {};
      for (let i = 0; i < checkboxlist.length; i++) {
        let arr = checkboxlist[i].split(/-/g);
        if (!list[arr[1]]) {
          list[arr[1]] = [arr[0]];
        } else {
          list[arr[1]] = [...list[arr[1]], arr[0]];
        }
      }
      // console.log(list,"???????")
      let messageList = deepClone(this.messageList);
      let filterlist = [];
      for (let i = 0; i < messageList.length; i++) {
        let item = list[i];
        if (item) {
          let messageItem = messageList[i];
          if (!item.includes("send")) {
            messageItem["send"] = "";
          }
          if (!item.includes("receive")) {
            messageItem["receive"] = "";
          }
          filterlist = [...filterlist, messageItem];
        }
        // messageList[i]
      }

      this.selectMessageList = filterlist;
      // console.log(
      //   this.checkboxlist,
      //   "############",
      //   this.messageList,
      //   this.selectMessageList
      // );
      // this.selectMessageList =
      this.imageSelectPopVisible = true;

      // setTimeout(() => {
      //   var ul = document.querySelector("#imageSelectHtml");
      //   ul.appendChild(node);
      // }, 1000);

      // console.log(
      //   this.checkboxlist,
      //   this.$refs["receive0"],
      //   this.$refs["receive0"][0].innerHTML,
      //   "#####"
      // );
    },
    downloadImage (index) {
      html2canvas(document.querySelector("#message-reply-cont" + index), {
        useCORS: true,
      }).then((canvas) => {
        var url = canvas.toDataURL(); //把canvas转成base64
        // 写一个隐藏的按标签，借助按标签的download属性下载图片
        document.querySelector("#downimg").href = url;
        document.querySelector("#downimg").download = "我的持仓报告.png";
        document.querySelector("#downimg").click();
      });
    },

    speakText (index) {
      let textToSpeak = this.messageList[index]["originreceive"];

      textToSpeak = textToSpeak.split(/#\*qsts:/)[0];
      textToSpeak = textToSpeak.replace(/#{1,}|-\s+|\*|-{1,}/g, "");
      if (textToSpeak.trim() !== "") {
        if (this.speechmsg) {
          speechSynthesis.cancel(this.speechmsg);
        }
        // this.speaking = true;
        this.speechmsg = new SpeechSynthesisUtterance(textToSpeak);

        speechSynthesis.speak(this.speechmsg);
      }
    },
    copyText (index) {
      this.toast("复制成功", "voice-copy" + index);
      const textarea = document.createElement("textarea");
      let copyText = this.messageList[index]["originreceive"];

      copyText = copyText.split(/#\*qsts:/)[0];
      copyText = copyText.replace(/#{1,}|-\s+|\*|-{1,}/g, "");
      // console.log(copyText);
      // console.log(copyText,"#########")
      textarea.value = copyText;
      document.body.appendChild(textarea);
      textarea.select();
      document.execCommand("copy");
      document.body.removeChild(textarea);
    },
    markmappop (markmapContent) {
      // console.log(markmapContent,"??????")
      this.markmapPopVisible = true;
      setTimeout(() => {
        this.markmapContent = markmapContent;
      }, 200);
    },
    markmaphandleClose () {
      this.markmapPopVisible = false;
      this.markmapContent = "";
    },
    imagepop (message) {
      // console.log(message, "????????");
      this.imagePopVisible = true;
      this.message = message;
    },
    handleClose () {
      // 处理关闭逻辑
      this.message = "";
    },
    keyDown () {
      this.handleSubmit();
    },
    linkToImagePage (message) {
      const routeData = this.$router.resolve({
        path: "/searchImagePage",
        query: { message },
      });
      window.open(routeData.href, "_blank");
      //  this.$router.push({path:"/searchImagePage",query:{message}})
    },
    linkToImageSlide (url) {
      window.open(url, "_blank");
    },
    hdlCmplete () {
      console.log("reder complete");
    },
    async messages_stop () {
      if (!this.taskId) return;
      let data = {
        user: this.name,
      };
      let res = await messagesStop(data, this.taskId);
    },
    handleClickOutside (event) {
      this.clearAutoScroll = true;
    },
    closepop (name) {
      if (name === "focus") {
        this.isfocus = false;
      } else if (name === "attachment") {
        this.isAttachment = false;
      }
    },
    initResize () {
      window.addEventListener("resize", this.resizeFunction, false);
    },
    removeResize () {
      window.removeEventListener("resize", this.resizeFunction);
    },
    resizeFunction () {
      this.questionLineNum = Math.floor(
        (this.$refs.home.offsetWidth - 130) / 160
      );
    },
    deleteAttachmentFile (key) {
      let attachmentFile = this.attachmentFile;
      let res = attachmentFile.filter((item, itemkey) => itemkey !== key);
      this.attachmentFile = res;
    },
    showAttachment () {
      this.isfocus = false;
      this.isAttachment = true;
    },
    handleFileUpload (file) {
      this.loading = true;
      const formData = new FormData();
      formData.append("file", file.file);
      formData.append("user", this.name);
      // 调用后端服务器的接口
      upload(formData)
        .then((resp) => {
          let isPic = /jpg|png|gif|jpeg/.test(resp.extension);
          this.attachmentFile = [
            ...this.attachmentFile,
            {
              name: resp.name,
              size: formatBytes(resp.size),
              extension: isPic ? "jpg" : resp.extension,
              id: resp.id,
            },
          ];
          this.isAttachment = false;
        })
        .catch((e) => {
          this.$message.error(e.message);
          this.$refs.upload.clearFiles();
        });
    },
    showpop (name) {
      if (name === "focus") {
        this.isfocus = true;
        this.isAttachment = false;
      } else if (name === "attachment") {
        this.isfocus = false;
        this.isAttachment = true;
      }
    },
    async conversations () {
      let data = {
        user: this.name,
        limit: 100,
      };
      let str = qs.stringify(data);
      await conversations(data);
    },
    // async chattopic() {
    //   let res = await chattopic();
    // },
    getchange (languagetype) {
      this.languagetype = languagetype;
      this.isfocus = false;
    },
    relationQuestionClick (event, arg) {
      if (/question-arrow/.test(event.target.className)) {
        if (this.buttonDisabled) return;
        let question = event.target.previousElementSibling.innerHTML;
        this.onConversation(question);
      } else if (/morerelation/.test(event.target.className)) {
        let childNodes = event.target.previousElementSibling.children;
        if (event.target.innerHTML === "更多") {
          for (let i = 0; i < childNodes.length; i++) {
            childNodes[i].className = "linkbox";
          }
          event.target.innerHTML = "收起";
        } else {
          for (let i = 0; i < childNodes.length; i++) {
            childNodes[i].className =
              i > this.questionLineNum ? "linkbox hidelinkbox" : "linkbox";
          }
          event.target.innerHTML = "更多";
        }
      }

      // event传不传都有
    },
    _computedWidth () {
      this.windowsclientWidth = document.body.clientWidth;
    },

    scrollToBottom () {
      this.$nextTick(() => {
        // scrollTo(document.documentElement.scrollHeight, 800, null);
        scrollTo(
          this.$parent.$el.scrollHeight,
          800,
          null,
          this.$parent.$el,
          this
        );
      });
    },
    handleSubmit () {
      // let totalJson = {"urls": ["[1]: https://nph.onlinelibrary.wiley.com/doi/abs/10.1111/nph.12157", "[2]: https://opentextbc.ca/plantidentification/chapter/plant-morphology-flowers-and-fruit/", "[3]: https://www.sciencedirect.com/science/article/abs/pii/S0889157509000192", "[4]: https://www.sciencedirect.com/science/article/abs/pii/S1146609X22000285", "[5]: https://www.ncbi.nlm.nih.gov/pmc/articles/PMC7473347/", "[6]: https://www.kloranebotanical.foundation/en/botany/botany-lessons/reference-sheet-fruits", "[7]: https://www.horticultureguruji.in/horticultural-and-botanical-classifications-of-fruits/", "[8]: https://en.wikipedia.org/wiki/Fruit", "[9]: https://www.sciencedirect.com/science/article/abs/pii/S089990071500180X", "[10]: https://thetroutbeckschool.com/the-botanical-classification-of-fruit/"], "titles": ["How colorful are fruits? Limited color diversity in fleshy fruits ...", "16. Plant Morphology – Flowers and Fruit", "Classification of fruits and vegetables - ScienceDirect", "Ecology of morphological fruit types, and fruit and seed ...", "Relationship between color and antioxidant capacity of fruits and ...", "Reference sheet: fruits | Klorane Botanical Foundation", "Horticultural and Botanical Classifications of Fruits - Horticulture ...", "Fruit - Wikipedia", "Classification of fruits based on anthocyanin types and relevance ...", "The botanical classification of fruit | The Troutbeck School"]}

      // this.receive = s;
      if (this.buttonDisabled) {
        if (this.duringTask) {
          this.messages_stop();
          this.duringTask = false;
        }
        return;
      }
      this.onConversation();
    },
    processData (text, type) {
      let _this = this;
      if (type === "object") {
        if (text["conversation_id"]) {
          if (!this.currentTopicId) {
            this.setCurrentTopicId(text["conversation_id"]);
          }
        } else if (text["titles"] && text["urls"]) {
          let urls = text["urls"];
          let titles = text["titles"];
          let titlecontent = "";
          _this.object = {};
          if (!(titles.length && urls.length)) {
            return;
          } else {
            let normal_titles = titles.filter(
              (item) => !["", null, undefined, NaN, false, true].includes(item)
            );
            let normal_urls = urls.filter(
              (item) => !["", null, undefined, NaN, false, true].includes(item)
            );
            if (!(normal_titles.length && normal_urls.length)) {
              return;
            }
          }
          titlecontent +=
            '<div class="model-title el-icon-connection">来源</div>';
          titlecontent += '<div class="linkboxTotal">';

          let length;
          let isMore;
          let questionLineNum = this.questionLineNum;
          if (text["urls"].length > questionLineNum) {
            length = questionLineNum;
            isMore = true;
          } else {
            length = text["urls"].length;
            isMore = false;
          }
          for (let i = 0; i < text["urls"].length; i++) {
            let titlekey = i;
            titlecontent +=
              '<div class="linkbox' +
              (i >= questionLineNum ? " hidelinkbox" : "") +
              '">';
            titlecontent +=
              '<div class="linktitle">' + titles[titlekey] + "</div>";
            let numLink = urls[titlekey].replace(/[\"\']/g, "").split(/\:\s+/);
            titlecontent +=
              '<div class="numlink">' +
              numLink[0] +
              '<div class="linkurl">' +
              numLink[1] +
              "</div>" +
              "</div>";
            titlecontent += "</div>";
          }
          titlecontent += "</div>";
          titlecontent += isMore ? '<div class="morerelation">更多</div>' : "";
          for (let i = 0; i < urls.length; i++) {
            let split = urls[i].split(/:(?!\/)/);
            if (split.length > 1) {
              let num = split[0].replace(/[\[\]]/g, "");
              if (!_this.object[num]) {
                _this.object[num] = {};
              }
              _this.object[num]["link"] = split[1].trim();
              _this.object[num]["title"] = titles[i].trim();
            }
          }

          if (Object.keys(_this.object).length) {
            titlecontent = titlecontent.replace(
              /\[(\d+)\](?!<\/span>)/g,
              (match, offset, string) => {
                let num = match.replace(/[\[\]]/g, "");
                let matchDiv;
                if (
                  _this.object[num] &&
                  _this.object[num]["title"] &&
                  _this.object[num]["link"]
                ) {
                  matchDiv =
                    "<span>" +
                    _this.object[num]["title"] +
                    '</span><a href="' +
                    _this.object[num]["link"] +
                    '" class="link" target="_blank">' +
                    _this.object[num]["link"] +
                    "</a>";
                }
                return matchDiv
                  ? '<span class="dotcontainer"><span class="boxdot">' +
                  num +
                  '</span><span class="dotText">' +
                  matchDiv +
                  "</span></span>"
                  : match;
              }
            );
          }

          // _this.titlecontent += titlecontent;
          _this.messageList[_this.messageList.length - 1].resource =
            titlecontent;
        } else if (text["questions"]) {
          let questionsList = text["questions"];
          if (questionsList && questionsList.length) {
            let titlecontent = '<ul class="related-question">';
            titlecontent +=
              '<div class="model-title el-icon-paperclip">相关的</div>';
            for (let i = 0; i < questionsList.length; i++) {
              if (questionsList[i]) {
                titlecontent +=
                  '<li><div class="question-content">' +
                  questionsList[i] +
                  '</div><div class="question-arrow el-icon-right"></div></li>';
              }
            }
            titlecontent += "</ul>";
            _this.titlecontent += titlecontent;
          }
        }
      } else {
        if (text && text.replace(/\s/g, "") === "[END]") {
          _this.messageList[_this.messageList.length - 1].loading = false;
          // _this.buttonDisabled = false;
          _this.eventSource = null;
          // _this.saveChatDetail();
          _this.abort.abort();
          _this.getchattopic();
          _this.scrollToBottom();
          _this.taskId = "";

          // console.log(_this.titlecontent,">>>>>>>>>>>>>>>>>")

          // _this.titlecontent = "$$\text{CaCO}_3 \\xrightarrow{\text{高温}} \text{CaO} + \text{CO}_2 \\uparrow$$";
          // console.log(_this.titlecontent, "###########");
          // _this.titlecontent = _this.titlecontent
          //   .replace(/\\\]/g, "$$$")
          //   .replace(/\\\[/g, "$$$");
        } else {
          // if (text.replace(/\s+/, "") === "") {
          //   return;
          // }
          // text = text.replace(/\n/g,"<br/>")

          // if (
          //   !/<div\s+class="model-title\s+el-icon-chat-dot-square">答案<\/div>/.test(
          //     _this.titlecontent
          //   )
          // ) {
          //   _this.titlecontent +=
          //     '<div class="model-title el-icon-chat-dot-square">答案</div>';
          //   console.log(text,_this.titlecontent)
          // }
          _this.messageList[_this.messageList.length - 1].originreceive += text;
          _this.titlecontent += text;
          _this.titlecontent = _this.titlecontent.replace(
            /((\*{2}\s*(\:|\：))\s*)(?!<br\/>)/g,
            "$2<br/>"
          );
        }
      }

      // if (!/(?<!#)#\s+.+/.test(_this.titlecontent) &&  /#{2,}\s+.+/.test(_this.titlecontent)) {
      //   _this.titlecontent = _this.titlecontent.replace(/#{2,}(.+)/, "#$1");
      // }
      // _this.titlecontent = _this.titlecontent
      //   .replace(/\s*\\\]/g, "$$$")
      //   .replace(/\\\[\s*/g, "$$$")
      //   .replace(/\\\(\s*/g, "$$")
      //   .replace(/\s*\\\)/g, "$$");

      if (Object.keys(_this.object).length) {
        _this.titlecontent = _this.titlecontent.replace(
          /\[(\d+)\](?!<\/span>)/g,
          (match, offset, string) => {
            let num = match.replace(/[\[\]]/g, "");
            let matchDiv;
            if (
              _this.object[num] &&
              _this.object[num]["title"] &&
              _this.object[num]["link"]
            ) {
              matchDiv =
                "<span>" +
                _this.object[num]["title"] +
                '</span>`<a href="' +
                _this.object[num]["link"] +
                '" class="link" target="_blank">' +
                _this.object[num]["link"] +
                "</a>`";
            }
            return matchDiv
              ? '<span class="dotcontainer"><span class="dot">' +
              num +
              '</span><span class="dotText">' +
              matchDiv +
              "</span></span>"
              : match;
          }
        );
      }
      // _this.titlecontent = _this.titlecontent.replace(/`{3}/g, "`");
      // _this.titlecontent = _this.titlecontent.replace(/(?<!#)(#)(?!#)(\s+)/,"$1$1$2")
      // _this.titlecontent = _this.titlecontent.replace(/(#{3})(?!\s+)/,"$1 ")
      //  _this.titlecontent = _this.titlecontent.replace(/(?<!#)#{1}(?!#)/g,"##")
      // _this.titlecontent = _this.titlecontent.replace(/[\r\n](#)/g,"$1");
      // _this.titlecontent = katex.renderToString(_this.titlecontent, {
      //   throwOnError: false,
      // });

      _this.messageList[_this.messageList.length - 1].receive =
        _this.titlecontent;
      if (Math.floor(_this.eventcount / 20) === _this.roundcount) {
        _this.scrollToBottom();
        _this.roundcount++;
      }
    },
    async changeTocurrentTopic (id, isLocal) {
      let currentChatList;
      this.messageList = [];
      if (id === "") {
        return;
      }
      if (isLocal) {
        currentChatList = this.chatList.filter(
          (item) => item.topic_id === id
        )[0].children;
        if (!(currentChatList && currentChatList.length)) return;
        for (let i = 0; i < currentChatList.length; i++) {
          this.messageList.push({
            send: currentChatList[i]["title"],
            receive: currentChatList[i]["content"],
            originreceive: currentChatList[i]["content"],
            imageList: [],
            markmapContent: "",
            isMarkmapContentDone: false,
            loading: false,
          });
        }
      } else {
        let queryuser = this.$route.query.user;
        let user = queryuser ? queryuser : this.name;
        let data = { user, conversation_id: id };
        let res = await messages(data);
        currentChatList = res.data;
        if (!(currentChatList && currentChatList.length)) return;

        for (let i = 0; i < currentChatList.length; i++) {
          if (!this.currentTopicId) {
            this.setCurrentTopicId(currentChatList[i]["conversation_id"]);
          }

          let resource = this.processAnswer(currentChatList[i]["answer"]);

          let totalResultAnswer = resource
            ? currentChatList[i]["answer"].match(/\n{2}[\s\S]+/)
            : currentChatList[i]["answer"];
          let resultAnwser;
          if (resource) {
            let totalResultAnswer =
              currentChatList[i]["answer"].match(/\n{2}[\s\S]+/);
            resultAnwser = totalResultAnswer
              ? totalResultAnswer[0]
              : currentChatList[i]["answer"];
          } else {
            resultAnwser = currentChatList[i]["answer"];
          }

          // let answer = currentChatList[i]["answer"]
          let question = currentChatList[i]["query"].replace(
            /[\s\S]*\[@SEP\]([\s\S]*)/,
            "$1"
          );
          // answer = answer
          //   .replace(/\s*\\\]/g, "$$$")
          //   .replace(/\\\[\s*/g, "$$$")
          //   .replace(/\\\(\s*/g, "$$")
          //   .replace(/\s*\\\)/g, "$$")
          //   .replace(/`{3}/g, "`");

          let message_files = currentChatList[i]['message_files']
          let attachmentFile = []
          message_files.forEach(item => {
            let extension = item.filename.split(/\./)[1]
            let isPic = /jpg|png|gif|jpeg/.test(extension);
            attachmentFile = [
              ...attachmentFile,
              {
                name: item.filename,
                size: formatBytes(item.size),
                extension: isPic ? "jpg" : extension,
                id: item.id,
              },
            ];
          })


          this.messageList.push({
            send: question.replace(/<p><\/p>/g, ""),
            resource: resource,
            attachmentFile: attachmentFile,
            receive: resultAnwser,
            originreceive: resultAnwser,
            imageList: [],
            markmapContent: "",
            isMarkmapContentDone: false,
            loading: false,
          });

          this.search_image(question, i);
          this.markmap(question, i);
        }
      }
    },
    processAnswer (answer) {
      let urls_str = answer.match(/urls:([\s\S]*)\[SEP\]/);
      let titlecontent;
      if (urls_str) {
        let urls =
          urls_str && urls_str[1]
            ? urls_str[1].split(/\n{1}(?!\n)/)    // split(/(?<!\n)\n{1}(?!\n)/)
            : [];
        urls = urls.filter((item) => !!item);
        let title_str = answer.match(/\[SEP\](([^\n]|\n{1}(?!\n))+)(?!\n{2})/);
     
        let titles =
          title_str && title_str[1]
            ? title_str[1].split(/\n{1}(?!\n)/)   // split(/(?<!\n)\n{1}(?!\n)/)
            : [];
        titles = titles.filter((item) => !!item);

        titlecontent = this.createLinkBox(titles, urls, answer);
      }

      return titlecontent;
    },

    createLinkBox (titles, urls, answer) {
      let _this = this;
      let titlecontent = "";
      _this.object = {};
      if (titles.length && urls.length) {
        let normal_titles = titles.filter(
          (item) => !["", null, undefined, NaN, false, true].includes(item)
        );
        let normal_urls = urls.filter(
          (item) => !["", null, undefined, NaN, false, true].includes(item)
        );
        if (!(normal_titles.length && normal_urls.length)) {
          return;
        }
        titlecontent +=
          "<div class='model-title el-icon-connection'>来源</div>";
        titlecontent += "<div class='linkboxTotal'>";
        let length;
        let isMore;
        let questionLineNum = this.questionLineNum;
        if (urls.length > questionLineNum) {
          length = questionLineNum;
          isMore = true;
        } else {
          length = urls.length;
          isMore = false;
        }
        for (let i = 0; i < urls.length; i++) {
          let titlekey = i;
          titlecontent +=
            '<div class="linkbox' +
            (i >= questionLineNum ? " hidelinkbox" : "") +
            '">';
          titlecontent +=
            '<div class="linktitle">' + titles[titlekey] + "</div>";
          let numLink = urls[titlekey].replace(/[\"\']/g, "").split(/\:\s+/);
          titlecontent +=
            '<div class="numlink">' +
            numLink[0] +
            '<div class="linkurl">' +
            numLink[1] +
            "</div>" +
            "</div>";
          titlecontent += "</div>";
        }
        titlecontent += "</div>";
        titlecontent += isMore ? '<div class="morerelation">更多</div>' : "";
        for (let i = 0; i < urls.length; i++) {
          let split = urls[i].split(/:(?!\/)/);
          if (split.length > 1) {
            let num = split[0].replace(/[\[\]]/g, "");
            if (!_this.object[num]) {
              _this.object[num] = {};
            }
            _this.object[num]["link"] = split[1].trim();

            _this.object[num]["title"] = titles[i].trim();
          }
        }

        if (Object.keys(_this.object).length) {
          titlecontent = titlecontent.replace(
            /\[(\d+)\](?!<\/span>)/g,    //   /(?<!<span\s+class\="boxdot">)\[(\d+)\](?!<\/span>)/g,
            (match, offset, string) => {
              let num = match.replace(/[\[\]]/g, "");
              let matchDiv;
              if (
                _this.object[num] &&
                _this.object[num]["title"] &&
                _this.object[num]["link"]
              ) {
                matchDiv =
                  "<span>" +
                  _this.object[num]["title"] +
                  '</span><a href="' +
                  _this.object[num]["link"] +
                  '" class="link" target="_blank">' +
                  _this.object[num]["link"] +
                  "</a>";
              }
              return matchDiv
                ? '<span class="dotcontainer"><span class="boxdot">' +
                num +
                '</span><span class="dotText">' +
                matchDiv +
                "</span></span>"
                : match;
            }
          );
        }
      }

      return titlecontent;
    },
    totalResultAnswerProcess (answer, callback) {
      let _this = this;
      // console.log(answer, "??????????????????????")
      let totalResultAnswer = answer.match(/\n{2}[\s\S]+/);

      let resultAnwser = totalResultAnswer ? totalResultAnswer[0] : answer;

      let resultAnwserList = resultAnwser.split(/#\*qsts:/);

      let mainAnswer = resultAnwserList[0] ? resultAnwserList[0] : "";
      mainAnswer = mainAnswer.replace(/(\n+)#{2}([\s\S]+)/, "$1#$2");

      mainAnswer = mainAnswer.replace(
        /<span\s+class="mopen">\[<\/span>((<span\s+class="mord">\d+<\/span>)+)<span\s+class="mclose">\]<\/span>/g,
        (match, content, ind, str, all) => {
          let num = content.replace(/[^\d]*(\d+)[^\d]*/g, "$1");

          let matchDiv;
          if (
            _this.object[num] &&
            _this.object[num]["title"] &&
            _this.object[num]["link"]
          ) {
            matchDiv =
              "<span>" +
              _this.object[num]["title"] +
              '</span><a href="' +
              _this.object[num]["link"] +
              '" class="link" target="_blank">' +
              _this.object[num]["link"] +
              "</a>";
          }
          return matchDiv
            ? '<span class="dotcontainer"><span class="dot">' +
            num +
            '</span><span class="dotText">' +
            matchDiv +
            "</span></span>"
            : match;
        }
      );
      mainAnswer = mainAnswer.replace(
        /\[(\d+)\](?!<\/span>)/g,
        (match, offset, string) => {
          let num = match.replace(/[\[\]]/g, "");
          let matchDiv;
          if (
            _this.object[num] &&
            _this.object[num]["title"] &&
            _this.object[num]["link"]
          ) {
            matchDiv =
              "<span>" +
              _this.object[num]["title"] +
              '</span><a href="' +
              _this.object[num]["link"] +
              '" class="link" target="_blank">' +
              _this.object[num]["link"] +
              "</a>";
          }
          return matchDiv
            ? '<span class="dotcontainer"><span class="dot">' +
            num +
            '</span><span class="dotText">' +
            matchDiv +
            "</span></span>"
            : match;
        }
      );

 
      mainAnswer =
        '<div class="model-title el-icon-chat-dot-square">答案</div>' +
        mainAnswer;
 
      let relatedAnswer = resultAnwserList[1];
      let questionscontent = "";
      if (relatedAnswer) {
        let questionsList = relatedAnswer.split(/\n+/);
        if (questionsList && questionsList.length) {
          questionscontent = '<ul class="related-question">';
          questionscontent +=
            '<div class="model-title el-icon-paperclip">相关的</div>';
          for (let i = 0; i < questionsList.length; i++) {
            let questions = questionsList[i].replace(/```/g, "");
            if (questions) {
              questionscontent +=
                '<li><div class="question-content">' +
                questions +
                '</div><div class="question-arrow el-icon-right"></div></li>';
            }
          }
          questionscontent += "</ul>";
        }
      }
      callback(mainAnswer + questionscontent);
    },
    async saveChatDetail () {
      let title = this.messageList[this.messageList.length - 1]["send"];
      let topic_id = this.currentTopicId;
      if (!topic_id) return;
      await addchatdetail({
        title,
        content: this.titlecontent,
        parent_id: topic_id,
      });
    },
    async search_image (message, index) {
      let res = await search_image({ query: message });
      this.messageList[index]["imageList"] = res;
    },
    async markmap (message, index) {
      let answer = "";
      let _this = this;
      _this.markmapabort = new AbortController();
      fetchEventSource("http://1.13.176.116:888/v1/chat-messages", {
        method: "POST",
        openWhenHidden: true,
        body: JSON.stringify({
          query: message,
          user: this.name,
          response_mode: "streaming",
          conversation_id: "",
          inputs: {},
        }),
        headers: {
          "Content-Type": "application/json",
          Accept: "text/event-stream",
          Authorization: "Bearer app-TTybm74kvzn9c454q3QXtC03",
        },
        onmessage (event) {
          if (event.data) {
            let data = JSON.parse(event.data);
            if (data["answer"]) {
              answer += data["answer"];
            }
            if (data["event"] === "message_end") {
              answer = answer.replace(/`{3}/g, "");
              // console.log(answer, "###");
              _this.messageList[index]["isMarkmapContentDone"] = true;
              _this.messageList[index]["markmapContent"] = answer;
              // console.log(answer)
              _this.markmapabort.abort();
            }
          } else {
            if (!_this.messageList[index]["isMarkmapContentDone"]) {
              // _this.messageList[index]["isMarkmapContentDone"] = true;
              // _this.messageList[index]["markmapContent"] = answer;
              // _this.markmapabort.abort();
            }
          }
        },
        onclose (ee) {
          // 关闭流
        },
        onerror (error) {
          throw error;
          //返回流报错
        },
      });

      // let markmap_res = await markmapreq({
      //   query: "老鹰",
      //   user: this.name,
      //   response_mode: "streaming",
      //   conversation_id: "",
      //   inputs: {},
      // });
    },
    async onConversation (question) {
      let _this = this;
      let message = question ? question : this.prompt;
      if (!message || message.trim() === "") return;

      // if (!this.currentTopicId && !this.chatfromdify) {
      //   let res = await addchattopic({ topic: message });
      //   _this.setCurrentTopicId(res.data["topic_id"]);
      // }
      this.clearAutoScroll = false;
      // Clear input box and disable button
      this.prompt = "";
      // this.buttonDisabled = true;
      this.fileUploadCard = false;
      this.titlecontent = "";
      this.eventcount = 0;
      this.roundcount = 0;
      this.taskId = "";

      // Send message (for local display, not directly sent to GPT)
      this.messageList.push({
        send: message,
        receive: "",
        attachmentFile: this.attachmentFile,
        originreceive: "",
        imageList: [],
        markmapContent: "",
        isMarkmapContentDone: false,
        loading: true,
      });
      this.scrollToBottom();

      // Stream request to ChatGPT3.5
      try {
        if (this.fileContent) {
          message += ", Uploaded file content: " + this.fileContent;
        }
        const UUID = v4();
        let data = {
          query: message,
          user: this.name,
          auto_generate: true,
          search_type: this.languagetype,
        };
        if (this.currentTopicId) {
          data["conversation_id"] = this.currentTopicId;
        }
        if (this.attachmentFile.length) {
          let file_ids = this.attachmentFile.map((item) => item.id);
          data["file"] = true;
          data["upload_file_ids"] = file_ids.join(",");
        }

        let str = qs.stringify(data);

        this.search_image(message, this.messageList.length - 1);
        this.markmap(message, this.messageList.length - 1);
        _this.attachmentFile = []
        this.abort = new AbortController();
        _this.buttonDisabled = true;
        this.eventSource = fetchEventSource("/v1/chat?" + str, {
          method: "POST",
          openWhenHidden: true,
          headers: {
            "Content-Type": "application/json",
            Accept: "text/event-stream",
            // Authorization: "Bearer app-3KCDfPYou8XURid07rwkSsOY",
          },
          onmessage (event) {

            let lastmessage = _this.messageList[_this.messageList.length - 1];
            _this.eventcount = _this.eventcount + 1;
            if (lastmessage) {
              lastmessage.loading = false;
            }
            if (event.data === "[END]") {
              _this.duringTask = false;
              _this.buttonDisabled = false;
              _this.processData(event.data, "string");
            } else {
              try {
                let eventdata = JSON.parse(event.data);

                let answer = eventdata["answer"];

                if (eventdata["answer"] === undefined) {
                  answer = eventdata;
                }
                if (typeof answer === "object") {
                  if (answer.task_id !== undefined) {
                    _this.taskId = answer.task_id;
                    _this.duringTask = true;
                    // console.log(answer.task_id, ">>>>>>>>>");
                  }

                  _this.processData(answer, "object");
                } else {
                  _this.processData(answer, "string");
                }
              } catch {
                _this.processData(event.data, "string");
              }
            }

            //   _this.processData(eventdata["answer"]);
            // 在这里操作流式数据
          },
          onclose (ee) {
            // 关闭流
          },
          onerror (error) {
            let lastmessage = _this.messageList[_this.messageList.length - 1];
            if (lastmessage) {
              lastmessage.loading = false;
            }

            throw error;
            //返回流报错
          },
        });

        this.fileName = "";
        this.fileSize = 0;
        this.formattedFileSize = "0B";
      } catch (e) {
        console.log(e);
      }
    },

    goTarget (href) {
      window.open(href, "_blank");
    },
  },
};
</script>

<style scoped lang="scss">
.share-btn-all {
  display: flex;
  justify-content: center;
  margin-top: 10px !important;
  li {
    margin: 0 5px;
    cursor: pointer;
  }
}
.chat-content-all {
  display: flex;
  flex-direction: column;
}
.copy-btn,
.downloadfile-btn,
.create-image-btn,
.copylink-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100px;
  background: #726df1;
  height: 30px;
  color: #fff;
  border-radius: 5px;
  .svg-icon {
    width: 20px;
    height: 20px;
    fill: #fff;
  }
}
.save-images-btns {
  display: flex;
  justify-content: center;
  padding-top: 10px !important;
  li {
    margin: 0 5px;
    cursor: pointer;
  }
}
.copy-btn {
  background: #9581df;
}
.downloadfile-btn {
  background: #7560d6;
}
.create-image-btn {
  color: #fff;
  background: #604bba;
  .svg-icon {
    fill: #fff;
  }
}
.copylink-btn {
  color: #fff;
  background: #f8b533;
  .svg-icon {
    fill: #fff;
  }
}
.create-image-disable-btn {
  color: #fff;
  background: #e5e7ed;
  .svg-icon {
    fill: #fff;
  }
}

.selectimagechatContent {
  overflow-y: auto;
}
.voice-copy {
  position: relative;
  display: flex;
  margin-top: 20px;

  .voice-icon {
    display: flex;
    justify-content: center;
    align-items: center;
    cursor: pointer;
    .svg-icon {
      width: 20px;
      height: 20px;
    }
  }
  .copy-icon {
    display: flex;
    justify-content: center;
    align-items: center;
    cursor: pointer;
    .svg-icon {
      width: 20px;
      height: 20px;
    }
  }
  .share-icon {
    display: flex;
    justify-content: center;
    align-items: flex-start;
    cursor: pointer;
    .svg-icon {
      width: 22px;
      height: 22px;
    }
  }
}
.imagepop-dialog,
.sharepop-dialog {
  top: 0px;
  left: 0px;
  right: 0px;
  bottom: 0px;
  overflow: hidden;
  ::v-deep .el-dialog {
    width: 100%;
    height: 100%;
    margin: 0 !important;
  }
}

.sharepop-dialog {
  .chat-content {
    height: 100%;
    overflow-y: auto;
  }
}

.selectimage-dialog {
  top: 50px;
  left: 50px;
  right: 50px;
  bottom: 50px;
  overflow: hidden;
  ::v-deep .el-dialog {
    width: 100%;
    height: 100%;
    margin: 0 !important;
  }
}

.mobile {
  .selectimage-dialog {
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
  }
}

.swiper-cont {
  width: 250px;
}
.guide-icon {
  fill: #fff;
  width: 20px;
  height: 20px;
  transform: scaleX(-1);
  margin-right: 0 !important;
}

.message-send-li {
  padding: 15px;
}

.mobile {
  .message-send-li {
    padding: 10px 0;
  }

  .message-reply-cont {
    padding: 10px 0 10px 0;
  }

  .message-answer-total {
    padding: 0 0 0 0;
  }
  .message-answer-all {
    flex-direction: column;
  }
}

.message-answer-all {
  display: flex;
}

.message-answer-total {
  padding: 0 15px 15px 15px;
  display: flex;

  .message-answer {
    width: 100%;
  }

  .message-row {
    width: 100%;
  }
  .message-content {
    width: 100%;
  }
  .message-answer-all {
    display: flex;
    flex: 1;
  }
  .message-reply-cont {
    flex: 1;
  }
}

.mobile {
  .message-answer-total {
    // flex-direction: column;
  }
}
.input-group-append {
  display: flex;
  align-items: center;
}
.upload-icon-txt {
  display: flex;
  align-items: center;
  .el-icon-upload {
    margin-right: 10px;
  }
}
.btn-close-svg {
  cursor: pointer;
  top: -10px;
  right: -10px;
  position: absolute;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  width: 20px;
  height: 20px;
  border: 1px solid #bdbdbd;
  background: #fff;
  svg {
    width: 16px;
    height: 16px;
    margin: 0;
    padding: 0;
  }
}
.fileIcon {
  width: 20px;
  height: 20px;
  margin-right: 5px;
  background-size: 16px;
}
.attachment-file {
  display: flex;
  font-size: 12px;
  .attachment-file-item {
    position: relative;
    width: 150px;
    padding: 10px;
    border: 1px solid #e9dccb;
    border-radius: 5px;
    background: #f3efe5;
    margin-right: 10px;
  }
  .attachment-file-item-htm,
  .attachment-file-item-html {
    border: 1px solid #f5d1b2;
    background: #fbeeda;
  }
  .attachment-file-item-jpg {
    border: 1px solid #dbd5ed;
    background: #f1eefd;
  }

  .attachment-file-item-xlsx,
  .attachment-file-item-xls {
    border: 1px solid #d2e9c7;
    background: #effde6;
  }
  .attachment-file-item-pdf {
    border: 1px solid #f8cfbc;
    background: #faebe2;
  }
  .attachment-file-item-docx,
  .attachment-file-item-doc {
    border: 1px solid #ced8f7;
    background: #e8efff;
  }
  .attachment-name {
    width: 100%;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    margin-bottom: 5px;
    .svg-icon {
      fill: #ed4c39;
    }
  }
}

.message-send-title {
  .attachment-file {
    margin-top: 10px;
    .attachment-name {
      margin-bottom: 0;
    }
  }
}

.svg-icon {
  margin-right: 5px;
}
.message-fill {
  display: flex;
  justify-content: space-between;
}
.languagetype {
  margin-right: 20px;
}
.mobile {
  .message-user-icon {
    margin-right: 10px;
  }
}

.message-user-ques {
  display: flex;
  min-height: 40px;
  background: #eef6ff;
  border-radius: 10px;
  padding: 15px;
  position: relative;
}
.message-user-ques::after {
  position: absolute;
  width: 0;
  height: 0;
  left: -8px;
  top: 18px;
  content: "";
  border-top: 7px solid transparent; /* 上边框透明 */
  border-right: 8px solid #eef6ff; /* 右边框为三角形的底部颜色 */
  border-bottom: 7px solid transparent; /* 下边框透明 */
}

.userprofile,
.message-reply-icon {
  display: flex;
  width: 40px;
  height: 40px;
  border-radius: 50%;
  align-items: center;
  justify-content: center;
  .reply-icon {
    display: flex;
    width: 20px;
    height: 20px;
  }
}

.message-reply {
  display: flex;
}

.message-reply-cont {
  padding: 10px 15px 10px 0;
}

.message-reply-icon {
  background: #167dd7;
}
.message-user-icon {
  display: flex;
  margin-right: 20px;
}
.align-items-center {
  align-items: center !important;
}

.input-group {
  position: relative;
  display: flex;
  flex-wrap: wrap;
  align-items: stretch;
  width: 100%;
}

.input-form-control {
  border: 0;
  height: 40px;
  font-size: 16px;
  width: 100%;
}
.el-icon-top {
  font-size: 24px;
}
.btn-submit-disable {
  width: 40px;
  height: 40px;
  border: 0;
  border-radius: 50% !important;
  background: #167dd7;
  .el-icon-top {
    color: #bdbdbd;
  }
}
.btn-submit-active {
  display: flex;
  justify-content: center;
  align-items: center;
  width: 40px;
  height: 40px;
  border: 0;
  border-radius: 50% !important;
  background: #167dd7;
  .el-icon-top {
    color: #fff;
  }
}
.form-control {
  position: relative;
  flex: 1 1 auto;
  width: 1%;
  min-width: 0;
}
.form-control {
  border-color: #f5f5f5;
  font-size: 14px;
  height: auto;
}

.border-0 {
  border: 0 !important;
}
.wave {
  position: relative;
  text-align: center;
  margin-left: auto;
  margin-right: auto;
  display: inline-flex;
  margin-left: 5px;
}
.wave .dot {
  display: inline-block;
  width: 3px;
  height: 3px;
  border-radius: 50%;
  margin-right: 5px;
  background: #167dd7;
  animation: wave 1.3s linear infinite;
}
.wave .dot:nth-child(2) {
  animation-delay: -1.1s;
}
.wave .dot:nth-child(3) {
  animation-delay: -0.9s;
}
@keyframes wave {
  0%,
  60%,
  100% {
    transform: initial;
  }
  30% {
    transform: translateY(-5px);
  }
}
.avatar.sm {
  height: 26px;
  width: 26px;
  font-size: 12px;
}
.rounded-circle {
  border-radius: 50% !important;
}
.message .avatar {
  border: 2px solid #167dd7;
}
.align-items-center {
  align-items: center !important;
}

.justify-content-end {
  justify-content: flex-end !important;
}
.chat-content .message .message-body {
  flex: 1;
}
.border,
.border-top,
.border-end,
.border-bottom,
.border-start {
  border-color: #f5f5f5 !important;
}
.border {
  border: 1px solid #f5f5f5 !important;
}
.p-3 {
  padding: 1rem !important;
}
.d-flex {
  display: flex !important;
}
.chat-content .message.right .message-content {
  background-color: transparent;
  text-align: left;
  border-radius: 15px 0 15px 15px;
}
.chat-content .message .message-content {
  border-radius: 0 15px 15px 15px;
  font-size: 16px;
}
.chat-content .message .message-send-title {
  display: flex;

  font-size: 18px;
  color: #3b3b3b;
  font-weight: bold;
}
.btn.btn-primary {
  background-color: #167dd7;
  border-color: #167dd7;
  width: 50px;
  height: 50px;
}
.chat-footer {
  position: fixed;
  display: flex;
  justify-content: center;
  width: 100%;
  bottom: 16px;
  margin: 0 auto;
  z-index: 999;
}

.chat-footer-in {
  position: relative;
  width: 800px;
  min-width: 0px;
  outline: 2px solid transparent;
  outline-offset: 2px;
  -webkit-appearance: none;
  -moz-appearance: none;
  -ms-appearance: none;
  appearance: none;
  // transition-property: $chakra-transition-property-common;
  // transition-duration: $chakra-transition-duration-normal;
  font-weight: 500;
  border-radius: 30px;
  // font-size: $chakra-fontSizes-sm;
  // -webkit-padding-start: $chakra-space-4;
  // padding-inline-start: $chakra-space-4;
  // -webkit-padding-end: $chakra-space-4;
  // padding-inline-end: $chakra-space-4;
  border: 1px solid #d4d4d4;
  // border-color: $chakra-colors-gray-200;
  background: inherit;

  padding: 15px 20px;
  background: #fff;
  // color: $chakra-colors-navy-700;
  .chat-focus-list {
    display: flex;
  }

  .chat-focus {
    display: flex;
    align-items: center;
    justify-content: center;
    background: rgba(39, 148, 235, 0.1);
    padding: 5px 10px;
    border-radius: 30px;
    color: #167dd7;
    margin-right: 10px;
    cursor: pointer;
    span {
      margin-right: 5px;
    }
  }
  .chat-focus-disable {
    background: rgba(0, 0, 0, 0.1);
    color: #585858;
  }

  .attachmentlist {
    display: flex;
    z-index: 1;
    position: absolute;
    background: #ffffff;
    color: #444444;
    width: 200px;
    height: 60px;
    align-items: center;
    padding: 20px;
    border-radius: 8px;
    border: 1px solid rgba(223, 223, 223, 0.5);
    background: rgba(255, 255, 255, 0.8);
    bottom: 50px;
    box-shadow: 0 1px 5px rgba(16, 24, 40, 0.1);
    .type-icon {
      display: flex;
    }
    .type-icon-active {
      color: #167dd7;
    }
    li {
      color: #676a6c;
      margin-right: 20px;
      cursor: pointer;
      .txt {
        margin-left: 10px;
      }
    }
  }

  .row {
    display: flex;
    justify-content: space-between;
    .row-fill-form {
      flex: 1;
      padding-right: 20px;
    }
  }
}
 
.home {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  position: relative;
  background-color: #fdfdfd;
  height: 100%;
  blockquote {
    padding: 10px 20px;
    margin: 0 0 20px;
    font-size: 17.5px;
    border-left: 5px solid #eee;
  }
  hr {
    margin-top: 20px;
    margin-bottom: 20px;
    border: 0;
    border-top: 1px solid #eee;
  }
  .col-item {
    margin-bottom: 20px;
  }

  ul {
    padding: 0;
    margin: 0;
  }

  font-family: "open sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
  font-size: 13px;
  color: #676a6c;

  ul {
    list-style-type: none;
  }

  h4 {
    margin-top: 0px;
  }

  h2 {
    margin-top: 10px;
    font-size: 26px;
    font-weight: 100;
  }

  p {
    margin-top: 10px;

    b {
      font-weight: 700;
    }
  }

  .update-log {
    ol {
      display: block;
      list-style-type: decimal;
      margin-block-start: 1em;
      margin-block-end: 1em;
      margin-inline-start: 0;
      margin-inline-end: 0;
      padding-inline-start: 40px;
    }
  }
}
</style>

<style lang="scss">
.katex {
  position: relative;
}
.markdown-body table {
  border-radius: 10px;
  overflow: visible;
  border: 1px solid #dfe2e5;
}
.markdown-body table tr {
  border-top: 1px solid #dfe2e5;
  width: 100%;
}
.markdown-body table td,
.markdown-body table th {
  border-top: none;
  border-left: none;
  border-bottom: none;
}
.markdown-body table th {
  &:first-child {
    border-radius: 10px 0 0 0;
  }
  &:last-child {
    border-radius: 0 10px 0 0;
  }
}
.markdown-body table tbody tr {
  &:last-child {
    td {
      &:first-child {
        border-radius: 0 0 10px 0;
      }
      &:last-child {
        border-radius: 0 0 10px 0;
      }
    }
  }
}
.markdown-body table thead tr {
  border-top: none;
}
.markdown-body table th {
  &:last-child {
    border-right: none;
  }
}
.markdown-body table td {
  &:last-child {
    border-right: none;
  }
}
.markdown-body table th {
  background: #f0f1f7;
}
.markdown-body .dotcontainer code {
  padding: 0;
  font-size: 100%;
  background-color: transparent;
  border-radius: 0;
  font-family: "open sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
}
ol li {
  list-style: decimal;
}

h1 {
  font-size: 18px;
  font-weight: bold;
  border-bottom: 0px;
}
h2,
h3 {
  font-size: 16px;
  font-weight: bold;
  border-bottom: 0px;
}

.container-low {
  padding-bottom: 140px;
}
.container-high {
  padding-bottom: 180px;
}
.dotcontainer {
  display: inline-block;
  position: relative;
  margin: 0 0 0 5px;
  cursor: pointer;
  .dot,
  .boxdot {
    display: inline-block;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    width: 16px;
    height: 16px;
    background: #167dd7;
    color: #fff;
    font-size: 12px;
    line-height: 0;
  }
  .dotText:hover {
    opacity: 1;
    visibility: visible;
  }
}
.dotcontainer:hover {
  .dotText {
    opacity: 1;
    visibility: visible;
  }
}

.dotText {
  position: absolute;
  transition: 0.5s;
  opacity: 0;
  visibility: hidden;
  top: 25px;
  left: 0;
  background: #167dd7;
  color: #fff;
  border-radius: 10px;
  padding: 10px;
  z-index: 2;
  width: 200px;
  font-size: 12px;
  span {
    display: block;
    margin-bottom: 5px;
    word-wrap: break-word;
    white-space: normal;
  }
  a {
    display: block;
    color: #fff !important;
    font-size: 12px;
    text-decoration: none;
    word-wrap: break-word;
    white-space: wrap;
    font-family: "open sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
  }
}
.dotText:hover {
  opacity: 1;
  visibility: visible;
}
.dotTextshow {
  display: block;
}
.linkboxTotal {
  display: flex;
  flex-wrap: wrap;
  margin-bottom: 10px;
  > div:last-child {
    margin-right: 0;
  }
}

.linkbox {
  position: relative;
  display: flex;
  justify-content: space-between;
  flex-direction: column;
  background: #eeeeee;
  max-width: 150px;
  margin-right: 10px;
  font-size: 12px;
  padding: 8px;
  border-radius: 5px;
  transition: all 0.5s;
  margin-bottom: 10px;
  .dotcontainer {
    position: static;
    margin: 0 5px 0 0;
  }
  .linktitle {
    color: #3b3b3b;
    text-overflow: ellipsis;
    overflow: hidden;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    width: 100%;
    margin-bottom: 10px;
    cursor: pointer;
  }
  .dotText {
    left: 50%;
    margin-left: -100px;
    top: 78px;
  }
  &:hover {
    background: #dfdfdf;
    .dotText {
      opacity: 1;
      visibility: visible;
    }
  }

  .dotText:hover {
    opacity: 1;
    visibility: visible;
  }
}

@keyframes fade-in {
  0% {
    opacity: 0;
  }
  100% {
    opacity: 1;
  }
}
@keyframes fade-out {
  0% {
    opacity: 1;
  }
  100% {
    opacity: 0;
  }
}

.hidelinkbox {
  display: none;
}

.linkurl {
  white-space: nowrap;
  text-overflow: ellipsis;
  overflow: hidden;

  -webkit-line-clamp: 1;

  width: 100%;
  code {
    background-color: transparent;
    font-size: 100%;
  }
}
.numlink {
  display: flex;
}
.related-question {
  margin: 10px 0 0 0 !important;
  padding-left: 0 !important;
  width: 100%;
  li {
    display: flex;
    justify-content: space-between;
    .question-content {
      display: flex;
      flex: 1;
    }
    .question-arrow {
      display: flex;
      width: 50px;
      align-items: center;
      color: #167dd7;
    }
  }
}
.vuepress-markdown-body a,
.vuepress-markdown-body p a code {
  color: #167dd7;
}

.model-title {
  display: block !important;
  font-size: 18px;
  color: #167dd7;
  font-weight: bold;
  margin-bottom: 10px !important;
  &::before {
    margin-right: 8px;
  }
}

.vuepress-markdown-body
  > div[data-v-md-line]:last-child
  > :last-child.model-title {
  margin-bottom: 10px !important;
}
.morerelation {
  cursor: pointer;
  color: #167dd7;
  margin-bottom: 20px;
}
</style>